home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / alib / csup / exec_support / CreateTask.c < prev    next >
C/C++ Source or Header  |  1994-02-15  |  7KB  |  236 lines

  1.  
  2. #include "exec/types.h"
  3. #include "exec/nodes.h"
  4. #include "exec/lists.h"
  5. #include "exec/memory.h"
  6. #include "exec/ports.h"
  7. #include "exec/tasks.h"
  8. #include "exec/libraries.h"
  9. #include "exec/execbase.h"
  10.  
  11. #include "V:include/clib/exec_protos.h"
  12.  
  13. extern VOID NewList(struct List *);
  14.  
  15. // extern APTR AllocMem();
  16. // extern struct Task *FindTask();
  17.  
  18. extern struct ExecBase *SysBase;
  19.  
  20.  
  21. /*
  22. ******* amiga.lib/CreateTask **************************************************
  23. *
  24. *   NAME
  25. *    CreateTask -- Create task with given name, priority, stacksize
  26. *
  27. *   SYNOPSIS
  28. *    task = CreateTask(name,pri,initPC,stackSize)
  29. *
  30. *    struct Task *CreateTask(STRPTR,LONG,funcEntry,ULONG);
  31. *
  32. *   FUNCTION
  33. *    This function simplifies program creation of sub-tasks by
  34. *    dynamically allocating and initializing required structures
  35. *    and stack space, and adding the task to Exec's task list
  36. *    with the given name and priority. A tc_MemEntry list is provided
  37. *    so that all stack and structure memory allocated by CreateTask()
  38. *    is automatically deallocated when the task is removed.
  39. *
  40. *    An Exec task may not call dos.library functions or any function
  41. *    which might cause the loading of a disk-resident library, device,
  42. *    or file (since such functions are indirectly calls to dos.library).
  43. *    Only AmigaDOS Processes may call AmigaDOS; see the
  44. *    dos.library/CreateProc() or the dos.library/CreateNewProc()
  45. *    functions for more information.
  46. *
  47. *    If other tasks or processes will need to find this task by name,
  48. *    provide a complex and unique name to avoid conflicts.
  49. *
  50. *    If your compiler provides automatic insertion of stack-checking
  51. *    code, you may need to disable this feature when compiling sub-task
  52. *    code since the stack for the subtask is at a dynamically allocated
  53. *    location.  If your compiler requires 68000 registers to contain
  54. *    particular values for base relative addressing, you may need to
  55. *    save these registers from your main process, and restore them
  56. *    in your initial subtask code.
  57. *
  58. *    The function entry initPC is generally provided as follows:
  59. *
  60. *    In C:
  61. *    extern void functionName();
  62. *    char *tname = "unique name";
  63. *    task = CreateTask(tname, 0L, functionName, 4000L);
  64. *
  65. *    In assembler:
  66. *        PEA    startLabel
  67. *
  68. *   INPUTS
  69. *    name - a null-terminated name string
  70. *    pri - an Exec task priority between -128 and 127, normally 0
  71. *    funcEntry - the address of the first executable instruction
  72. *            of the subtask code
  73. *    stackSize - size in bytes of stack for the subtask. Don't cut it
  74. *            too close - system function stack usage may change.
  75. *
  76. *   RESULT
  77. *    task - a pointer to the newly created task, or NULL if there was not
  78. *           enough memory.
  79. *
  80. *   BUGS
  81. *    Under exec.library V37 or beyond, the AddTask() function used
  82. *    internally by CreateTask() can fail whereas it couldn't fail in
  83. *    previous versions of Exec. Prior to amiga.lib V37.14, this function
  84. *    did not check for failure of AddTask() and thus might return a
  85. *    pointer to a task structure even though the task was not actually
  86. *    added to the system.
  87. *
  88. *   SEE ALSO
  89. *    DeleteTask(), exec/FindTask()
  90. *
  91. ******************************************************************************
  92. */
  93.  
  94.  
  95. /*
  96.  *  Create a task with given name, priority, and stack size.
  97.  *  It will use the default exception and trap handlers for now.
  98.  */
  99. /* the template for the mementries.  Unfortunately, this is hard to
  100.  * do from C: mementries have unions, and they cannot be statically
  101.  * initialized...
  102.  *
  103.  * In the interest of simplicity I recreate the mem entry structures
  104.  * here with appropriate sizes.  We will copy this to a local
  105.  * variable and set the stack size to what the user specified,
  106.  * then attempt to actually allocate the memory.
  107.  */
  108.  
  109. #define ME_TASK     0
  110. #define ME_STACK    1
  111. #define NUMENTRIES    2
  112.  
  113. struct FakeMemEntry
  114. {
  115.     ULONG fme_Reqs;
  116.     ULONG fme_Length;
  117. };
  118.  
  119. struct FakeMemList
  120. {
  121.     struct Node fml_Node;
  122.     UWORD    fml_NumEntries;
  123.     struct FakeMemEntry fml_ME[NUMENTRIES];
  124. } TaskMemTemplate = {
  125.     { 0 },                        /* Node */
  126.     NUMENTRIES,                     /* num entries */
  127.     {                            /* actual entries: */
  128.     { MEMF_PUBLIC | MEMF_CLEAR, sizeof( struct Task ) },    /* task */
  129.     { MEMF_CLEAR,    0 }                    /* stack */
  130.     }
  131. };
  132.  
  133.  
  134.  
  135.  
  136. struct Task *CreateTask( name, pri, initPC, stackSize )
  137.     char *name;
  138.     UBYTE pri;
  139.     APTR  initPC;
  140.     ULONG stackSize;
  141. {
  142.     struct Task *newTask;
  143. //    ULONG memSize;
  144.     struct FakeMemList fakememlist;
  145.     struct MemList *ml;
  146.     ULONG result;
  147.  
  148.     /* round the stack up to longwords... */
  149.     stackSize = (stackSize +3) & ~3;
  150.  
  151.     /*
  152.      * This will allocate two chunks of memory: task of PUBLIC
  153.      * and stack of PRIVATE
  154.      */
  155.     fakememlist = TaskMemTemplate;
  156.     fakememlist.fml_ME[ME_STACK].fme_Length = stackSize;
  157.  
  158.     ml = (struct MemList *) AllocEntry( (struct MemList *)&fakememlist );
  159.  
  160.     if( ! ml ) {
  161.     return( NULL );
  162.     }
  163.  
  164.     /* set the stack accounting stuff */
  165.     newTask = (struct Task *) ml->ml_ME[ME_TASK].me_Addr;
  166.  
  167.     newTask->tc_SPLower = ml->ml_ME[ME_STACK].me_Addr;
  168.     newTask->tc_SPUpper = (APTR)((ULONG)(newTask->tc_SPLower) + stackSize);
  169.     newTask->tc_SPReg = newTask->tc_SPUpper;
  170.  
  171.     /* misc task data structures */
  172.     newTask->tc_Node.ln_Type = NT_TASK;
  173.     newTask->tc_Node.ln_Pri = pri;
  174.     newTask->tc_Node.ln_Name = name;
  175.  
  176.     /* add it to the tasks memory list */
  177.     NewList( &newTask->tc_MemEntry );
  178.     AddHead( &newTask->tc_MemEntry, (struct Node *)ml );
  179.  
  180.     /* add the task to the system -- use the default final PC */
  181.  
  182.     result = (ULONG)AddTask( newTask, initPC, 0 );
  183.     if ((SysBase->LibNode.lib_Version >= 37) && (result == 0))
  184.     {
  185.         FreeEntry(ml);
  186.         return(NULL);
  187.     }
  188.     return( newTask );
  189. }
  190.  
  191.  
  192. /*
  193. ******* amiga.lib/DeleteTask *************************************************
  194. *
  195. *   NAME
  196. *    DeleteTask -- delete a task created with CreateTask()
  197. *
  198. *   SYNOPSIS
  199. *    DeleteTask(task)
  200. *
  201. *    VOID DeleteTask(struct Task *);
  202. *
  203. *   FUNCTION
  204. *    This function simply calls exec.library/RemTask(), deleting a task
  205. *    from the Exec task lists and automatically freeing any stack and
  206. *    structure memory allocated for it by CreateTask().
  207. *
  208. *    Before deleting a task, you must first make sure that the task is
  209. *    not currently executing any system code which might try to signal
  210. *    the task after it is gone.
  211. *
  212. *    This can be accomplished by stopping all sources that might reference
  213. *    the doomed task, then causing the subtask to execute a Wait(0L).
  214. *    Another option is to have the task call DeleteTask()/RemTask() on
  215. *    itself.
  216. *
  217. *   INPUTS
  218. *    task - task to remove from the system
  219. *
  220. *   NOTE
  221. *    This function simply calls exec.library/RemTask(), so you can call
  222. *    RemTask() directly instead of calling this function.
  223. *
  224. *   SEE ALSO
  225. *    CreateTask(), exec.library/RemTask()
  226. *
  227. ******************************************************************************
  228. */
  229.  
  230.  
  231. DeleteTask(tc)
  232.     struct Task *tc;
  233. {
  234.     RemTask(tc);
  235. }
  236.